package ldh.serialize.util;

import ldh.serialize.io.ByteBuf;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

public class CompressionUtil {

	private static final int BUFFER_SIZE = 4 * 1024;

	public static byte[] compress(byte[] data, Level level) throws IOException {

		Deflater deflater = new Deflater();
		// set compression level
		deflater.setLevel(level.getLevel());
		deflater.setInput(data);

		ByteArrayOutputStream outputStream = new ByteArrayOutputStream(
				data.length);

		deflater.finish();
		byte[] buffer = new byte[BUFFER_SIZE];
		while (!deflater.finished()) {
			int count = deflater.deflate(buffer); // returns the generated
													// code... index
			outputStream.write(buffer, 0, count);
		}
		byte[] output = outputStream.toByteArray();
		outputStream.close();
		return output;
	}

	public static byte[] decompress(byte[] data) throws IOException, DataFormatException {
		Inflater inflater = new Inflater();
		inflater.setInput(data);

		ByteArrayOutputStream outputStream = new ByteArrayOutputStream(
				data.length);
		byte[] buffer = new byte[BUFFER_SIZE];
		while (!inflater.finished()) {
			int count = inflater.inflate(buffer);
			outputStream.write(buffer, 0, count);
		}
		byte[] output = outputStream.toByteArray();
		outputStream.close();
		return output;
	}
	
	public static enum Level {  
		  
        /** 
         * Compression level for no compression. 
         */  
        NO_COMPRESSION(0),  
  
        /** 
         * Compression level for fastest compression. 
         */  
        BEST_SPEED(1),  
  
        /** 
         * Compression level for best compression. 
         */  
        BEST_COMPRESSION(9),  
  
        /** 
         * Default compression level. 
         */  
        DEFAULT_COMPRESSION(-1);  
  
        private int level;  
  
        Level(  
  
        int level) {  
            this.level = level;  
        }  
        public int getLevel() {  
            return level;  
        }  
    }  
	
	public static byte[] intToByte(Integer intValue) {
		List<Byte> list = new ArrayList<Byte>();
	    if (intValue == null) {
	        return null;
	    }
	    //遍历列表中的每个正整数。
        while (intValue > 0) {
            int byteOf = intValue & 0x7f; //得到正整数的低7位。
            if (intValue < 128) {
                //如果n值已经能由7位表示，则该字节是最后一个字节。
                byteOf = intValue + 128; //将该字节的最高位置为1。
                list.add((byte) byteOf);
            } else {
                list.add((byte) byteOf);
            }
            intValue = intValue >> 7;
        }
//	    if (intValue < 128) {
//	    	return new byte[]{(byte)(intValue & 0x7f)};
//	    } else if (intValue <= 32767) {
//	    	byte[] t = new byte[2];
//	    	t[0] = (byte)(intValue & 0xff);
//	    	t[1] = (byte)((intValue & 0x7fff) >> 8);
//	    	return t;
//	    } else if (intValue <= 0x7fffff) {
//	    	byte[] t = new byte[3];
//	    	t[0] = (byte)(intValue & 0xff);
//	    	t[1] = (byte)((intValue & 0x7fff) >> 8);
//	    	t[2] = (byte)((intValue & 0x7fffff) >> 16);
//	    	return t;
//	    } else if (intValue <= 0x7fffffff) {
//	    	byte[] t = new byte[4];
//	    	t[0] = (byte)(intValue & 0xff);
//	    	t[1] = (byte)((intValue & 0x7fff) >> 8);
//	    	t[2] = (byte)((intValue & 0x7fffff) >> 16);
//	    	t[3] = (byte)((intValue & 0x7fffffff) >> 24);
//	    	return t;
//	    } else {
//	    	byte[] t = new byte[5];
//	    	t[0] = (byte)(intValue & 0xff);
//	    	t[1] = (byte)((intValue & 0x7fff) >> 8);
//	    	t[2] = (byte)((intValue & 0x7fffff) >> 16);
//	    	t[3] = (byte)((intValue & 0x7fffffff) >> 24);
//	    	t[3] = (byte)1;
//	    	return t;
//	    }
	    byte[] tt = new byte[list.size()];
	    int i = 0;
	    for (Byte b : list) {
	    	tt[i++] = b;
	    }
	    return tt;
	}
	
	public static Integer byteToInt(byte[] byteList) {
	    int n = 0;
	    int byteStartPerInt = 0;
	    for (int i = 0, l = byteList.length; i < l; i++) {
	        //依次读取字节数组。
	        if (byteList[i] >= 0) {
	            //如果当前字节的值大于0，则表示最高位是0，该字节不是最后的字节。
	            n += byteList[i] * Math.pow(128, i - byteStartPerInt);
	        } else {
	            //如果当前字节的值小于0，则表示最高位是1，该字节是最后的字节。
	            n += (byteList[i] + 128) * Math.pow(128, i - byteStartPerInt);
	            byteStartPerInt = i + 1;
	        }
	    }
	    return n;
	}
	
	public static Integer byteToVarInt(ByteBuf in) throws IOException {
	    int n = 0;
	    int i = 0;
	    while(true) {
	    	byte value = (byte) in.readByte();
	    	if (value >= 0) {
	    		n += value * Math.pow(128, i++);
	    	} else {
	    		n += (value + 128) * Math.pow(128, i);
	    		break;
	    	}
	    }
	    
	    return n;
	}
}
